package net.hekka.canyoutalk.web.processor;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.naming.NamingException;
import net.hekka.canyoutalk.data.constant.ConnectionConstant;
import net.hekka.canyoutalk.data.executor.NumberTableSqlExecutor;
import net.hekka.canyoutalk.data.executor.TempLogQuerySqlExecutor;
import net.hekka.canyoutalk.data.executor.TempLogTableSqlExecutor;
import net.hekka.canyoutalk.data.vo.TempLogTableVo;
import net.hekka.canyoutalk.share.database.DataSourceConnector;
import net.hekka.canyoutalk.share.property.RequestParameterProperties;

/**
 * TempLogTable의 데이터를 관리하기 위한 프로세서 이다.
 * @author Jeffrey Ha
 */
public class LogRegisterProcessor {

    private boolean test = false;

    /**
     * 생성자
     */
    public LogRegisterProcessor() {
    }

    /**
     * 테스트 생성자
     * @param test true면 테스트 파일
     */
    public LogRegisterProcessor(boolean test) {
        this.test = test;
    }

    public int registerTempLog(RequestParameterProperties requestParameterProperties) {
        int returnValue = 0;
        TempLogTableVo tempLogTableVo;
        Connection dbConnection = null;
        int maxSequence = 0;

        try {
            System.out.println("[registerTempLog] RequestParameterProperties: " + requestParameterProperties.toString());
            tempLogTableVo = new TempLogTableVo();

            // get database connection
            dbConnection = getConnection();
            // start database transaction.
            dbConnection.setAutoCommit(false);

            String myNumber = requestParameterProperties.getProperty("mynumber");
            tempLogTableVo.setMyNumber(myNumber);

            // Packet Text
            String packetText = requestParameterProperties.getProperty("packet_text");
            tempLogTableVo.setPacketData(packetText);

            // packet 분리
            StringTokenizer stringTokenizer = new StringTokenizer(packetText, " ");

            // StringTokenizer를 ArrayList 로 이동
            List<String> packetList = new ArrayList<String>();
            while (stringTokenizer.hasMoreTokens()) {
                packetList.add(stringTokenizer.nextToken());
            }

            String yourNumber = null;
            String status = null;

            if (packetList.get(0).equals("ILN")) {
                yourNumber = packetList.get(2);
                status = packetList.get(1);

                // 상태변경 전화번호 데이터 중 maxSequence 를 구한다.
                maxSequence = getMaxSequence(dbConnection, yourNumber);

            } else if (packetList.get(0).equals("CHG")) {
                yourNumber = "";
                status = packetList.get(2);
            } else {
                yourNumber = "";
                status = "";
            }

            tempLogTableVo.setYourNumber(yourNumber);
            tempLogTableVo.setStatus(status);
            tempLogTableVo.setLinkSequence(maxSequence);

            String checkNumber = requestParameterProperties.getProperty("check_num");
            if ("true".equals(checkNumber)) {
                tempLogTableVo.setCheckNumber("t");
            } else {
                tempLogTableVo.setCheckNumber("f");
            }

            // Busy Minutes
            long busyMin = Long.parseLong(requestParameterProperties.getProperty("busy_min"));
            if (busyMin > 0) {
                long today = System.currentTimeMillis();
                System.out.println("## today : " + today);
                long secToday = (long) (today / 1000);
                System.out.println("## secToday : " + secToday);
                busyMin += (9 * 60 * 60); // 9시간을 초(sec)로 변환
                System.out.println("## busyMin (9 hour plus) : " + busyMin);
                busyMin = (long) ((busyMin - secToday) / 60); // busyMin에서 현재시간을 뺀 값을 분(min.)으로 변환
                System.out.println("## busyMin (difference with today) : " + busyMin);
            }
            tempLogTableVo.setBusyMinute(busyMin);

            System.out.println("TempLogTableVo : " + tempLogTableVo.toString());

            // TempLogTable 입력
            returnValue = registerTempLog(dbConnection, tempLogTableVo);

            // NumberTable에 존재하지 않으면 등록한다.
            if (packetList.get(0).equals("ILN")) {
                boolean isExisted = isExistedInNumbertable(dbConnection, yourNumber, myNumber);

                System.out.println("[registerTempLog] isExisted" + isExisted);
                if (isExisted == false) {
                    returnValue = registerNumbertable(dbConnection, yourNumber, myNumber);
                }
            }

        } catch (SQLException ex) {
            Logger.getLogger(LogRegisterProcessor.class.getName()).log(Level.SEVERE, null, ex);
        } catch (NamingException ex) {
            Logger.getLogger(LogRegisterProcessor.class.getName()).log(Level.SEVERE, null, ex);
        } catch (Exception ex) {
            Logger.getLogger(LogRegisterProcessor.class.getName()).log(Level.SEVERE, null, ex);
        } finally {
            try {
                // database transaction end
                dbConnection.setAutoCommit(true);
            } catch (SQLException ex) {
            }
            cleanup(dbConnection);
            return returnValue;
        }
    }

    private int registerTempLog(Connection connection, TempLogTableVo tempLogTableVo) throws SQLException {
        int returnValue = 0;

        TempLogTableSqlExecutor tempLogTableSqlExecutor = new TempLogTableSqlExecutor();
        returnValue = tempLogTableSqlExecutor.insertTempLogTable(connection, tempLogTableVo);
        return returnValue;
    }

    private int getMaxSequence(Connection connection, String yourNumber) throws SQLException {
        int maxSequence = 0;
        TempLogQuerySqlExecutor tempLogQuerySqlExecutor = new TempLogQuerySqlExecutor();
        maxSequence = tempLogQuerySqlExecutor.getMaxSequenceOfMyNumber(connection, yourNumber);
        return maxSequence;
    }

    private boolean isExistedInNumbertable(Connection connection, String owner, String friend) throws SQLException {
        int count = 0;
        NumberTableSqlExecutor numberTableSqlExecutor = new NumberTableSqlExecutor();
        count = numberTableSqlExecutor.getCountOfNumberTable(connection, owner, friend);
        if (count > 0) {
            return true;
        } else {
            return false;
        }
    }

    private int registerNumbertable(Connection connection, String owner, String friend) throws SQLException {
        int count = 0;
        NumberTableSqlExecutor numberTableSqlExecutor = new NumberTableSqlExecutor();
        return numberTableSqlExecutor.insertNumberTable(connection, owner, friend);
    }

    private Connection getConnection() throws SQLException, NamingException, Exception {
        Connection dbConnection = null;
        if (test) {
            dbConnection = DatabaseTestConnector.getConnection();
        } else {
            dbConnection = DataSourceConnector.getConnection(ConnectionConstant.databaseType);
        }
        return dbConnection;
    }

    private void cleanup(Connection con) {
        DataSourceConnector.cleanup(con);
    }
}
